Skip to content

fix(painter): stop the typing flicker from synchronized updates - #1304

Open
kronberger-droid wants to merge 1 commit into
nushell:mainfrom
kronberger-droid:fix/1302-sync-flicker
Open

kronberger-droid wants to merge 1 commit into
nushell:mainfrom
kronberger-droid:fix/1302-sync-flicker

Conversation

@kronberger-droid

@kronberger-droid kronberger-droid commented Nov 11, 2026 •

Copy link
Copy Markdown
Collaborator

Summary

#1254 wrapped every repaint in a synchronized update (CSI ? 2026 h ... CSI ? 2026 l).
Since then typing flickers under tmux, under zellij and in Alacritty on Windows, see #1302.
A repaint no longer opens a frame.

No public API change.
The observable change is the escape sequence stream of a repaint.

Before

One repaint is SGR 0, ?25l, ?2026h, clear, prompt, buffer, ?25h, ?2026l.
Multiplexers do not pass mode 2026 through, they hold the pane and redraw it themselves when the frame ends.

After

A repaint is a single write of clear, prompt and buffer with no frame around it, as it was before #1254.
The frame around an external printer commit (#1257) stays.
A new frame_open flag on the painter makes the repaint after it end that frame, and only that one.

Testing

Tested by mkatychev in #1302 on macOS under tmux with --example basic: main flickers, this branch does not.
Moving the cursor hide inside the frame instead, the other candidate this branch carried, did not help and is dropped.

Additional notes

fixes #1302

Bringing the bracket back for paints that span several writes is out of scope here.

With the bracket from nushell#1254, typing flickers under tmux, under zellij
and in Alacritty on Windows (nushell#1302), and reverting nushell#1254 as a whole
cured it there.

The likely mechanism, read from the tmux source and not reproduced:
multiplexers do not pass mode 2026 through. tmux (3.7 and later) holds
the pane and redraws every touched row when the frame ends, and since
each repaint clears from the prompt row down, that is every row to the
bottom of the pane on every keystroke.

A normal repaint is far below the writer's 8 KiB buffer and reaches
the terminal as one write, so the bracket bought nothing there. If it
comes back, it should be limited to paints that span several writes.

The frame around an external-message commit (nushell#1257) stays, since that
one does span two writes. The repaint after it still has to end it,
thus `frame_open`: a paint ends a frame only when one is open.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

bug: prompt flickering on input sync issue

1 participant